﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Threading;
using System.Windows.Navigation;
using Microsoft.Devices;
using com.google.zxing;
using com.google.zxing.common;
using com.google.zxing.qrcode;
using System.IO.IsolatedStorage;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;

namespace Senior_Project
{
    public partial class CameraPage : PhoneApplicationPage
    {
        bool check;
        Data FoodData;                  // set class object [FoodData class]
        UserProfile profile;
        App app = App.Current as App;   // set for global variable


        //set variable to use Camera of device and Scan QR code
		private readonly DispatcherTimer _timer;        
		private readonly ObservableCollection<string> _matches;        
		private PhotoCameraLuminanceSource _luminance;        
		private QRCodeReader _reader;        
		private PhotoCamera _photoCamera;
        public IEnumerable<Size> size;

        static string[] SplitWords(string s)
        {
            //
            // Split on all non-word characters.
            // ... Returns an array of all the words.
            //
            return Regex.Split(s, @"\W+");
            // @      special verbatim string syntax
            // \W+    one or more non-word characters together
        }

        public CameraPage()
        {
            InitializeComponent();
			_matches = new ObservableCollection<string>();
            
            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromMilliseconds(250);
            _timer.Tick += (o, arg) => ScanPreviewBuffer();
        }
		
		protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            _photoCamera = new PhotoCamera();
            _photoCamera.Initialized += OnPhotoCameraInitialized;            
            _previewVideo.SetSource(_photoCamera);

            CameraButtons.ShutterKeyHalfPressed += (o, arg) => _photoCamera.Focus();

            base.OnNavigatedTo(e);
        }
		
		private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
        {
            //set width and height of CameraViewer, binding with Resolution[width, height] of device
            int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
            int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);

            _luminance = new PhotoCameraLuminanceSource(width, height);
            _reader = new QRCodeReader();

            Dispatcher.BeginInvoke(() => {
                _previewTransform.Rotation = _photoCamera.Orientation;
                _timer.Start();
            });
        }

		private void ScanPreviewBuffer()
        {
            try
            {
                _photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
                var binarizer = new HybridBinarizer(_luminance);
                var binBitmap = new BinaryBitmap(binarizer);
                var result = _reader.decode(binBitmap);
                Dispatcher.BeginInvoke(() => DisplayResult(result.Text));    //call DisplayResult method to show output
            }
            catch
            {
            }            
        }


        //************************************* set format, show and save data from Scan QR code ************************************
        private void DisplayResult(string text)
        {
            // set XElement for get text in qr code [xml tag format]
            try
            {
                check = true;
                XElement element = XElement.Parse(text);
                var items = from item in element.Descendants("NT")
                            select FoodData = new Data
                            {
                                Fid = item.Element("id").Value,
                                Name = item.Element("n").Value,
                                Weight = item.Element("w").Value,
                                Calory = item.Element("c").Value,
                                Protein = item.Element("p").Value,
                                Fat = item.Element("f").Value,
                                Carbohydrate = item.Element("cb").Value,
                                Calcium = item.Element("ca").Value,
                                PhosPhorus = item.Element("k").Value,
                                Iron = item.Element("i").Value
                            };
                // check items
                int count = items.Count();
            }
            catch 
            {
                check = false;
                MessageBox.Show("Input Type is Wrong, Please try again !!"); 
            }


            if (check)
            {
                // set format for display to MessageBox
                string result = "Name : " + FoodData.Name + "\n" +
                                "Weight : " + FoodData.Weight + " g." + "\n" +
                                "Fat : " + FoodData.Fat + " g." + "\n" +
                                "Iron : " + FoodData.Iron + " g." + "\n" +
                                "Calory : " + FoodData.Calory + " kcal." + "\n" +
                                "Calcium : " + FoodData.Calcium + " g." + "\n" +
                                "Protein : " + FoodData.Protein + " g." + "\n" +
                                "PhosPhorus : " + FoodData.PhosPhorus + " g." + "\n" +
                                "Carbohydrate : " + FoodData.Carbohydrate + " g." + "\n";


                // show to MessageBox and Save(); data to Isolated Storage File [TempXML.xml]
                if (MessageBox.Show(result, "Result", MessageBoxButton.OKCancel) != MessageBoxResult.Cancel)
                {
                    // call saveData method
                    saveData();
                    CheckTarket();
                }
                else { }
            }
            else { }
            
        }
        //*******************************************************************************************************************



        //******************************************** saveData() method ****************************************************
        public void saveData()
        {
            // set variable refer to IsolatedStorageFile
            using (IsolatedStorageFile myIsolated = IsolatedStorageFile.GetUserStoreForApplication())
            {
                // check file exist >> 
                // file exits -> update TempXML.xml (add element items) 
                if (myIsolated.FileExists("TempXML.xml"))
                {
                    // set variable refer to XDocument
                    XDocument doc;
                    using (IsolatedStorageFileStream isoStream = myIsolated.OpenFile("TempXML.xml", FileMode.Open, FileAccess.Read))
                    {
                        // load TempXML.xml in Open mode
                        doc = XDocument.Load(isoStream);
                        DateTime datetime = DateTime.Now;
                        string[] w = SplitWords(datetime.ToString());
                        string date = w[2] + "-" + w[0] + "-" + w[1];
                        string time = w[3] + ":" + w[4] + ":" + w[5] + " " + w[6];
                        

                        // create element and value
                        XElement element = new XElement("food",
                                                new XElement("date", date),
                                                new XElement("time", time),
                                                new XElement("id", FoodData.Fid),
                                                new XElement("name", FoodData.Name),
                                                new XElement("weight", FoodData.Weight),
                                                new XElement("calory", FoodData.Calory),
                                                new XElement("protein", FoodData.Protein),
                                                new XElement("fat", FoodData.Fat),
                                                new XElement("carbohydrate", FoodData.Carbohydrate),
                                                new XElement("calcium", FoodData.Calcium),
                                                new XElement("phosphorus", FoodData.PhosPhorus),
                                                new XElement("iron", FoodData.Iron)
                                            );
                        // add element to Root document
                        doc.Root.Add(new XElement(element));
                    }

                    // set variable refer to IsolatedStorageFileStream and StreamWriter
                    using(IsolatedStorageFileStream isolatedStorageFileStream = myIsolated.OpenFile("TempXML.xml", FileMode.Open, FileAccess.Write))
                    {
                        using(var file = new StreamWriter(isolatedStorageFileStream))
                        {
                            // save new element to file
                            doc.Save(file);
                        }
                    }
                  
                }
                // file no exit -> create TempXML.xml file
                else
                {
                    // set variable refer to IsolatedStorageFileStream
                    using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("TempXML.xml", FileMode.Create, FileAccess.Write, myIsolated))
                    {
                        // set variable refer to XmlWriterSetting
                        XmlWriterSettings setting = new XmlWriterSettings();
                        setting.Indent = true;

                        // set variable refer to XmlWriter
                        using (XmlWriter writer = XmlWriter.Create(isoStream, setting))
                        {
                            // create element and value
                            DateTime datetime = DateTime.Now;
                            string[] w = SplitWords(datetime.ToString());
                            string date = w[2] + "-" + w[0] + "-" + w[1];
                            string time = w[3] + ":" + w[4] + ":" + w[5] + " " + w[6];

                            writer.WriteStartElement("n", "nutrition", "upn:nutrition");

                            writer.WriteStartElement("food");

                            writer.WriteStartElement("date");
                            writer.WriteString(date);
                            writer.WriteEndElement();

                            writer.WriteStartElement("time");
                            writer.WriteString(time);
                            writer.WriteEndElement();

                            writer.WriteStartElement("id");
                            writer.WriteString(FoodData.Fid);
                            writer.WriteEndElement();

                            writer.WriteStartElement("name");
                            writer.WriteString(FoodData.Name);
                            writer.WriteEndElement();

                            writer.WriteStartElement("weight");
                            writer.WriteString(FoodData.Weight);
                            writer.WriteEndElement();

                            writer.WriteStartElement("calory");
                            writer.WriteString(FoodData.Calory);
                            writer.WriteEndElement();

                            writer.WriteStartElement("protein");
                            writer.WriteString(FoodData.Protein);
                            writer.WriteEndElement();

                            writer.WriteStartElement("fat");
                            writer.WriteString(FoodData.Fat);
                            writer.WriteEndElement();

                            writer.WriteStartElement("carbohydrate");
                            writer.WriteString(FoodData.Carbohydrate);
                            writer.WriteEndElement();

                            writer.WriteStartElement("calcium");
                            writer.WriteString(FoodData.Calcium);
                            writer.WriteEndElement();

                            writer.WriteStartElement("phosphorus");
                            writer.WriteString(FoodData.PhosPhorus);
                            writer.WriteEndElement();

                            writer.WriteStartElement("iron");
                            writer.WriteString(FoodData.Iron);
                            writer.WriteEndElement();

                            writer.WriteEndElement();

                            // end document
                            writer.WriteEndDocument();

                            // writer to file
                            writer.Flush();
                        }
                    }
                }
                //*************************************************************************************************************


                
                //#############################################################################################################
                // ******************************** for check xml file show to MessageBox *************************************
                string test;
                try
                {
                    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        IsolatedStorageFileStream isoFileStream = myIsolatedStorage.OpenFile("TempXML.xml", FileMode.Open);
                        using (StreamReader reader = new StreamReader(isoFileStream))
                        {
                            test = reader.ReadToEnd();
                            MessageBox.Show(test, "result", MessageBoxButton.OK);
                        }
                    }
                }
                catch { MessageBox.Show("File not found !"); }
                //************************************************************************************************************
                //myIsolated.DeleteFile("TempXML.xml");
                //############################################################################################################
            }
        }


        // ************************************* CheckTarket Method for recomment to user *************************************
        public void CheckTarket()
        {
            // sum value of each value
            double sumCalorie = 0, sumProtein = 0, sumFat = 0;
            DateTime date = DateTime.Now;
            string[] d = SplitWords(date.ToString());
            string day = d[1];
            string month = d[0];
            string mode = "", mode1 = "diet", mode2 = "kidney", mode3 = "diabetes";
            double calorie_limit = 0, protein_limit = 0, fat_limit = 0;

            // ====================== Open TempXML.xml for get nutrition data ==========================
            string test;
            try
            {
                // set variable refer to IsolatedStorageFile
                using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    // set variable refer to IsolatedStorageFileStream
                    IsolatedStorageFileStream isoFileStream = myIsolatedStorage.OpenFile("TempXML.xml", FileMode.Open, FileAccess.Read);
                    using (StreamReader reader = new StreamReader(isoFileStream))
                    {
                        // read to end xml file
                        test = reader.ReadToEnd();

                        if (test != null)
                        {
                            // set element value
                            XElement element = XElement.Parse(test);
                            var items = from item in element.Descendants("food")
                                        select new Data
                                        {
                                            Date = item.Element("date").Value,
                                            Calory = item.Element("calory").Value,
                                            Protein = item.Element("protein").Value,
                                            Fat = item.Element("fat").Value
                                        };


                            // calculate SUM of nutrition data
                            foreach (var sumItems in items)
                            {
                                string[] word = sumItems.Date.Split('-');
                                if (word[2] == day && word[1] == month)
                                {
                                    sumCalorie += Convert.ToDouble(sumItems.Calory);
                                    sumProtein += Convert.ToDouble(sumItems.Protein);
                                    sumFat += Convert.ToDouble(sumItems.Fat);
                                }
                            }
                        }
                        else { MessageBox.Show("file is empty !"); }
                    }
                }
            }
            catch
            {
                MessageBox.Show("File not found !");
            }
            // ==================================================================================


            //=================== open userXML.xml file for get uid =================
            // open userXML.xml file and read data
            string text;
            try
            {
                // set variable refer to IsolatedStorageFile
                using (IsolatedStorageFile myIsolatedStorage1 = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    // set variable refer to IsolatedStorageFileStream
                    IsolatedStorageFileStream isoFileStream1 = myIsolatedStorage1.OpenFile("userXML.xml", FileMode.Open);
                    using (StreamReader reader = new StreamReader(isoFileStream1))
                    {
                        // read to end file
                        text = reader.ReadToEnd();


                        // set element for feed data from userXML.xml file
                        XElement element = XElement.Parse(text);
                        var items1 = from item1 in element.Descendants("user")
                                     select profile = new UserProfile
                                     {
                                         Disease = item1.Element("disease").Value,
                                         Calorie_Limit = item1.Element("calorie_limit").Value,
                                         Protein_Limit = item1.Element("protein_limit").Value,
                                         Fat_Limit = item1.Element("fat_limit").Value
                                     };
                        int count1 = items1.Count();
                        if (count1 == 1)
                        {
                            mode = profile.Disease;
                            if (string.Compare(mode, mode1) == 0)
                            {
                                calorie_limit = Convert.ToDouble(profile.Calorie_Limit);
                            }
                            if (string.Compare(mode, mode2) == 0)
                            {
                                protein_limit = Convert.ToDouble(profile.Protein_Limit);
                            }
                            if (string.Compare(mode, mode3) == 0)
                            {
                                fat_limit = Convert.ToDouble(profile.Fat_Limit);
                            }
                        }
                        else MessageBox.Show("can not read userXML.xml file");
                    }
                }
            }
            catch
            {
                MessageBox.Show("userXML.xml not found !");
            }
            //========================================================================


            // diet case
            if (string.Compare(mode, mode1) == 0)
            {
                double remaining = calorie_limit - sumCalorie;
                if (remaining < 300)
                {
                    string output = "Your calorie limit is " + calorie_limit + " kcal./day" + "\n" +
                                    "Today you gets " + sumCalorie + " kcal." + "\n\n" +
                                    "It's going to the amount your limit already. You should receive reduced a amount of calories.";

                    MessageBox.Show(output, "Recommend", MessageBoxButton.OK);
                }
            }


            // kidney case
            if (string.Compare(mode, mode2) == 0)
            {
                double remaining = protein_limit - sumProtein;
                if (remaining < 10)
                {
                    string output = "Should not get Protein more than " + protein_limit + " g." + "\n" +
                                    "Today you gets " + sumProtein + " g." + "\n\n" +
                                    "It's going to the amount your limit already. You should receive reduced a amount of protein.";

                    MessageBox.Show(output, "Recommend", MessageBoxButton.OK);
                }
            }


            // diabetes case
            if (string.Compare(mode, mode3) == 0)
            {
                double remaining = fat_limit - sumFat;
                if (remaining < 100)
                {
                    string output = "You should not get Fat more than " + fat_limit + " g." + "\n" +
                                    "Today you gets " + sumFat + " g." + "\n\n" +
                                    "It's going to the amount your limit already. You should receive reduced a amount of fat.";

                    MessageBox.Show(output, "Recommend", MessageBoxButton.OK);
                }
            }
        }
        // ********************************************************************************************************************


        // BackKeyPress click >> dispose camera and clear variable
        private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _photoCamera.Dispose();
            _luminance = null;
            _reader = null;
            _timer.Stop();
        }
    }
}